﻿using System;
using System.Windows;
using System.Windows.Controls;
using Riba.MVVMSL;
using Microsoft.Silverlight.Testing;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTest
{
	internal class MyChildWindow : ChildWindow
	{
	}

	internal class MyPropertyClass
	{
		public int ID { get; set; }
		public string Name { get; set; }
	}

	internal class MyViewModel2 : ViewModelBase
	{
	}

	internal class MyViewModel : ViewModelBase
	{
		public string MyFunc()
		{
			return null;
		}

		private int _myPropSimple;
		public int MyPropSimple
		{
			get { return _myPropSimple; }
			set { SetPropertyValue(ref _myPropSimple, value, () => MyPropSimple); }
		}

		private MyPropertyClass _myPropComplex;
		public MyPropertyClass MyPropComplex
		{
			get { return _myPropComplex; }
			set { SetPropertyValue(ref _myPropComplex, value, () => MyPropComplex); }
		}

		private string _myPropNullTest;
		public string MyPropNullTest
		{
			get { return _myPropNullTest; }
			set { SetPropertyValue(ref _myPropNullTest, value, null); }
		}

		private string _myPropNotAMember;
		public string MyPropNotAMember
		{
			get { return _myPropNotAMember; }
			set { SetPropertyValue(ref _myPropNotAMember, value, () => MyFunc()); }
		}

		public object CommandParameter { get; set; }

		public RelayCommand Command1 { get; private set; }

		public MyViewModel()
		{
			Command1 = new RelayCommand(OnCommand1);
		}

		private void OnCommand1(object commandParameter)
		{
			CommandParameter = commandParameter;  //Instrumentalisierung für Unit Test
		}
	}

	[TestClass]
	public class Tests : SilverlightTest
	{
		#region Instruments

		private string _propName;
		private bool _isCalled;
		private object _parameter;
		private MessageBoxResult _msgBoxResult;
		private object _commandParameter;
		private bool _canExecuteChangedCalled;

		#endregion Instruments

		//[TestMethod]
		//[Timeout(5000)]
		//[Asynchronous]
		//public void Test_Async()
		//{
		//  var vm = new MyViewModel();
		//  EnqueueCallback(() => vm.Command1.CanExecute());
		//  EnqueueCallback(() => Assert.IsTrue(_isCalled));
		//  EnqueueTestComplete();
		//}

		[TestMethod]
		[Tag("1")]
		public void Test_RelayCommand()
		{
			var command = new RelayCommand(ExcecuteHandler);
			command.CanExecuteChanged += command_CanExecuteChanged;

			Assert.IsFalse(_canExecuteChangedCalled);
			Assert.IsFalse(command.CanExecute(null));

			Assert.IsTrue(_commandParameter == null);
			command.Execute(1);
			Assert.IsTrue((int)_commandParameter == 1);

			command.IsEnabled = true;
			Assert.IsTrue(_canExecuteChangedCalled);
			Assert.IsTrue(command.CanExecute(null));
		}

		public void ExcecuteHandler(object commandParameter)
		{
			_commandParameter = (int)commandParameter;
		}
		void command_CanExecuteChanged(object sender, EventArgs e)
		{
			_canExecuteChangedCalled = true;
		}

		[TestMethod]
		[Tag("2")]
		public void Test_Command_IsEnabled()
		{
			_isCalled = false;

			var vm = new MyViewModel();
			vm.Command1.CanExecuteChanged +=
				(sender, e) =>
				{
					_isCalled = true;
				};

			vm.Command1.IsEnabled = true;
			var b = vm.Command1.CanExecute(1);
			Assert.IsTrue(b);
			Assert.IsTrue(_isCalled);
		}

		[TestMethod]
		[Tag("3")]
		public void Test_Command_Parameter()
		{
			var vm = new MyViewModel();
			vm.Command1.Execute(123);
			Assert.IsTrue((int)vm.CommandParameter == 123);
		}

		[TestMethod]
		[Tag("4")]
		public void Test_Show_MessageBox()
		{
			var vm = new MyViewModel();
			vm.ShowMsgBox += (sender, e) => e.Callback(MessageBoxResult.OK);

			vm.RaiseShowMsgBox(new ViewModelBase.ShowMsgBoxEventArgs("Inhalt", "Titel", MessageBoxButton.OKCancel, messageBoxResult => _msgBoxResult = messageBoxResult));

			Assert.IsTrue(_msgBoxResult == MessageBoxResult.OK);
		}

		[TestMethod]
		[Tag("5")]
		public void Test_Load_View()
		{
			var vm = new MyViewModel();
			vm.LoadChildWindow += (sender, e) => e.Callback(new MyViewModel2(), 54321);

			vm.RaiseLoadChildWindow(new ViewModelBase.LoadChildWindowEventArgs(typeof(MyChildWindow), 12345, CallbackAction));

			Assert.IsTrue((int)_parameter == 54321);
		}

		public void CallbackAction(ViewModelBase viewModel, object parameter)
		{
			_parameter = parameter;
		}

		[TestMethod]
		[Tag("6")]
		[ExpectedException(typeof(ArgumentException))]
		public void Raise_ArgumentException()
		{
			var vm = new MyViewModel();
			vm.MyPropNotAMember = "test";
		}

		[TestMethod]
		[Tag("7")]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Raise_ArgumentNullException()
		{
			var vm = new MyViewModel();
			vm.MyPropNullTest = "test";
		}

		[TestMethod]
		[Tag("8")]
		public void Test_simple_property()
		{
			var vm = new MyViewModel();
			vm.PropertyChanged += vm_PropertyChanged;
			vm.MyPropSimple = 1;
			Assert.IsTrue(_propName == "MyPropSimple");
		}

		[TestMethod]
		[Tag("9")]
		public void Test_complex_property()
		{
			var vm = new MyViewModel();
			vm.PropertyChanged += vm_PropertyChanged;
			vm.MyPropComplex = new MyPropertyClass { ID = 1, Name = "Ein Name" };
			Assert.IsTrue(_propName == "MyPropComplex");
		}

		void vm_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
		{
			_propName = e.PropertyName;
		}
	}
}